/**
 * This file is part of the dspace-poltman project http://www.poltman.com.
 *
 * This is free software; you can redistribute it and/or modify it under
 * the terms of DuraSpace DSpace license detailed in the LICENSE and NOTICE 
 * files at the root of the source tree and available online at
 * http://www.dspace.org/license/
 * 
 */
package com.poltman.dscentral.epeople;

import java.util.List;

import org.apache.log4j.Logger;
import org.dspace.core.Context;
import org.dspace.eperson.AccountManager;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.annotation.Propagation;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zkplus.spring.SpringUtil;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listcell;
import org.zkoss.zul.Messagebox;

import com.poltman.dscentral.core.ConfigurationManager;
import com.poltman.dscentral.core.CoreSessionData;
import com.poltman.dscentral.db.entity.dspace.EPersonEntity;
import com.poltman.dscentral.db.entity.pm.BaseUserEntity;
import com.poltman.dscentral.db.entity.pm.MainMenuGroupsEntity;
import com.poltman.dscentral.db.service.dspace.EPersonService;
import com.poltman.dscentral.db.service.pm.LanguagesService;
import com.poltman.dscentral.extended.services.EPersonExtendedService;
import com.poltman.dscentral.utils.LDAPLookup;
import com.poltman.dscentral.utils.Validators;


/**
 * 
 * @author Zbigniew Ciok; z.ciok@poltman.com
 * @version $Revision: 1815 $
 * 
 */
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public class AddEPeopleFormVM extends AddEPeopleForm {
	

	private static Logger log = Logger.getLogger(AddEPeopleFormVM.class);
	
	
	public String insertGridWidth = "350px";
	
	public boolean authRowVisible = false;
	public boolean isAuthRowVisible() {
		return authRowVisible;
	}
	public void setAuthRowVisible(boolean authRowVisible) {
		this.authRowVisible = authRowVisible;
	}
	
	//TODO: move it to AddEPeopleModel.java
	//visibility messages
	public boolean userIdMsgVisible = false;
	public boolean lastNameMsgVisible = false;
	public boolean firstNameMsgVisible = false;	
	public boolean ldapEmailMsgVisible = false;
	public boolean authenticationMsgVisible = false;
	

	//save user
	@SuppressWarnings("unchecked")
	@Command
	@NotifyChange({"insertGridWidth", 
				   "userIdMsgVisible", 
				   "lastNameMsgVisible", 
				   "firstNameMsgVisible",
				   "ldapEmailMsgVisible",
				   "authenticationMsgVisible", 
				   "eperson"})
    public void save() {
		
		CoreSessionData coreSessionData = (CoreSessionData) SpringUtil.getBean("coreSessionData");		
		
		//Gets menu groups shortcuts
		List<String> userMenuShortcuts = (List<String>) coreSessionData.getAttribute("userMenuShortcuts");
//		for (int i = 0; i < userMenuShortcuts.size(); i++) {
//			log.info("User Menu Group Shortcut " + userMenuShortcuts.get(i));
//		}	
		
		
    	EPersonEntity epersonEntity = new EPersonEntity();
    	
    	epersonEntity.setFirstname(eperson.getFirstName());
    	epersonEntity.setLastname(eperson.getLastName());
    	epersonEntity.setPhone(eperson.getPhone());
    	epersonEntity.setLanguage(coreSessionData.getSelectedLanguageCode());
    	
    	epersonEntity.setCanLogIn(eperson.getCanLogIn());
    	epersonEntity.setRequireCertificate(eperson.getRequiredCertificate());
    	epersonEntity.setSelfRegistered(null);
    	epersonEntity.setNetid(null);
    	
    	//Language Code selection
    	LanguagesService  languagesService = (LanguagesService) SpringUtil.getBean("languagesService");
    	String languageCode = "";
    	try {
    		String lang = "";
    		lang = eperson.getLanguage();
    		if (lang == null) lang = "";
    		if ("".equals(lang)) {
    			languageCode = null;
    		} else languageCode = languagesService.findByName(eperson.getLanguage()).getCode();
    	} catch (Exception e) {
			Messagebox.show("Languae Error.", "DSCentral Error", 0,  Messagebox.ERROR);
			return;    		
    	}
    	epersonEntity.setLanguage(languageCode);
    	
    	//DSCentral Operator 
    	BaseUserEntity baseUserEntity = new BaseUserEntity();
    	boolean userIdAsEmailValidation = true;
    	if (eperson.getDscentralOperator()) {
    		//TODO: enum authentication method
    		if (!"Password".equals(eperson.getAuthentication())) {
    			userIdAsEmailValidation = false;
    			epersonEntity.setEmail(eperson.getUserEmail());
    			
    			userIdMsgVisible = false;
    			firstNameMsgVisible = false;
    			lastNameMsgVisible = false;
       			ldapEmailMsgVisible = false;    			
    		} else {
    			userIdAsEmailValidation = true;
    			epersonEntity.setEmail(eperson.getUserId());
    		}
    		baseUserEntity.setDscAuthenticationMethod(eperson.getAuthentication());
    		//epersonEntity.setCanLogIn(true);
    	} else {
    		baseUserEntity = null;
			epersonEntity.setEmail(eperson.getUserId());
			epersonEntity.setNetid(null);    		
    	}
    	
    	//After validation
    	if (validate(userIdAsEmailValidation)) {
    		//Does eperson.getEmail() exist?
    		try {
    			EPersonService epersonService = (EPersonService) SpringUtil.getBean("epersonService");
    			EPersonEntity sEperson = (EPersonEntity) epersonService.findByEmail(epersonEntity.getEmail());
    			if (sEperson != null) {
    				if (epersonEntity.getEmail().equals(sEperson.getEmail())) {
    					Messagebox.show("User with " + epersonEntity.getEmail() + " already exists.", "DSCentral Error", 0,  Messagebox.ERROR);
    					return;
    				}
    			}	
    		} catch (Exception e) {
    			Messagebox.show("Save error", "DSCentral Error", 0,  Messagebox.ERROR);
    			log.error("Save new EPerson error. ", e);
    			return;
    		}
    		
    		//send registration email
    		try {
    			Context context = (Context) SpringUtil.getBean("context");
    			Boolean dSCentralOperator;
    			if (eperson.getDscentralOperator()) {
    				//TODO: enum authentication method
    				dSCentralOperator = true;
    				if ("Password".equals(eperson.getAuthentication()) || "LDAP".equals(eperson.getAuthentication())) {    		
    					AccountManager.sendRegistrationInfo(context, epersonEntity.getEmail(), dSCentralOperator);
    				}
    			} else {
    				dSCentralOperator = false;
    				AccountManager.sendRegistrationInfo(context, epersonEntity.getEmail(), dSCentralOperator);
    			}
    		} catch (Exception e) {
    			log.error("AddEPeopleFromVM; save eperson; send registration email error.", e);
    			Messagebox.show("Send registration email error.", "DSCentral Error", 0, Messagebox.ERROR);
    			return;
    		}
  		
    		//Save
    		EPersonExtendedService epersonExtendedService = (EPersonExtendedService) SpringUtil.getBean("epersonExtendedService");
    		try {
    			epersonExtendedService.addEPerson(epersonEntity, baseUserEntity, userMenuShortcuts);
    		} catch (Exception e) {
    			Messagebox.show("Add EPerson Error (epersonExtendedService.addEPerson)", "DSCentral Error", 0,  Messagebox.ERROR);
    			return;
    		}
    		
    		clearForm();  
    	}
    }
	

	@Command
	@NotifyChange("eperson")
	public void ldapSearch() {
		log.info("ldap search - LDAP / X.509");
		
		String userId = "";
		userId = eperson.getUserId();
		
		if ((userId == null) || (userId.isEmpty())) {
			Messagebox.show("Enter user (LDAP cn)", "DSCentral Error", 0,  Messagebox.ERROR);
			return;
		}
		String[] answer = new String[4];
		log.info("userId = " + userId);
		answer = LDAPLookup.search(userId);
		
		if ((answer[0] == null) || (answer[0].isEmpty())) {
			Messagebox.show("Empty LDAP user email (or LDAP server error)", "DSCentral Error", 0,  Messagebox.ERROR);
			return;
		}
		
		eperson.setFirstName(answer[1]);
		eperson.setLastName(answer[2]);
		eperson.setUserEmail(answer[0]);
		eperson.setPhone(answer[3]);
	}


	/**
	 * 
	 */
	private void clearForm() {
		String username = ConfigurationManager.getProperty("mail.server.username");
		Messagebox.show(eperson.getUserId() + " has been saved. \n\nNotification mail has been sent from " + username, "DSCentral", 0, Messagebox.INFORMATION);
		
		eperson.setUserId("");
		eperson.setFirstName("");
		eperson.setLastName("");
		eperson.setPhone("");
		eperson.setUserEmail("");
		eperson.setCanLogIn(false);
		eperson.setRequiredCertificate(false);
	}
	
	
	//validation
	/**
	 * Validate Add EPeople form
	 * @return
	 */
	private boolean validate(boolean userIdAsEmailValidation) {
		boolean valid = true;
		if (userIdAsEmailValidation) {
			if (!Validators.isValidEmailAddress(eperson.getUserId())) {
				valid = false;
				this.setUserIdMsgVisible(true);
			} else this.setUserIdMsgVisible(false);
		} else {
			if ((eperson.getUserId() == null) || ("".equals(eperson.getUserId()))) {
				valid = false;
				this.setUserIdMsgVisible(true);
			} else this.setUserIdMsgVisible(false);
		}
    	
    	if ((eperson.getFirstName() == null) || "".equals(eperson.getFirstName())) {
    		valid = false;
    		this.setFirstNameMsgVisible(true);
    	} else this.setFirstNameMsgVisible(false);

    	if ((eperson.getLastName() == null) || "".equals(eperson.getLastName())) {
    		valid = false;
    		this.setLastNameMsgVisible(true);
    	} else this.setLastNameMsgVisible(false);
    	
    	if (eperson.getDscentralOperator()) {
        	if ((eperson.getAuthentication() == null) || "".equals(eperson.getAuthentication())) {
        		valid = false;
        		this.setAuthenticationMsgVisible(true);
        	} else this.setAuthenticationMsgVisible(false);
        	
       		if ((eperson.getUserId() == null) || "".equals(eperson.getUserId())) {
       			valid = false;
       			this.setLdapEmailMsgVisible(true);
       		} else this.setLdapEmailMsgVisible(false);
    	}
    	
    	if ((eperson.getLastName() == null) || "".equals(eperson.getLastName())) {
    		valid = false;
    		this.setLastNameMsgVisible(true);
    	} else this.setLastNameMsgVisible(false);    	
    	
    	if (valid) {
    		this.setInsertGridWidth("350px");
    	} else {
    		this.setInsertGridWidth("550px");
    	}
    	return valid;
	}
	
	
	//visibility messages
	
	public boolean isLastNameMsgVisible() {
		return lastNameMsgVisible;
	}
	public boolean isUserIdMsgVisible() {
		return userIdMsgVisible;
	}

	public void setUserIdMsgVisible(boolean userIdMsgVisible) {
		this.userIdMsgVisible = userIdMsgVisible;
	}

	public void setLastNameMsgVisible(boolean lastNameMsgVisible) {
		this.lastNameMsgVisible = lastNameMsgVisible;
	}
	
	public boolean isFirstNameMsgVisible() {
		return firstNameMsgVisible;
	}
	public void setFirstNameMsgVisible(boolean firstNameMsgVisible) {
		this.firstNameMsgVisible = firstNameMsgVisible;
	}

	public String getInsertGridWidth() {
		return insertGridWidth;
	}
	public void setInsertGridWidth(String insertGridWidth) {
		this.insertGridWidth = insertGridWidth;
	}

	public boolean isLdapEmailMsgVisible() {
		return ldapEmailMsgVisible;
	}
	public void setLdapEmailMsgVisible(boolean ldapEmailMsgVisible) {
		this.ldapEmailMsgVisible = ldapEmailMsgVisible;
	}
	
	public boolean isAuthenticationMsgVisible() {
		return authenticationMsgVisible;
	}
	public void setAuthenticationMsgVisible(boolean authenticationMsgVisible) {
		this.authenticationMsgVisible = authenticationMsgVisible;
	}
}
